package com.ffcs.crmd.tsp.task.core;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;

import com.ffcs.crmd.tsp.api.dto.heart.HeartbeatData;
import com.ffcs.crmd.tsp.api.dto.heart.TaskData;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.exception.TspException;
import com.ffcs.crmd.tsp.common.exception.TspRemotingException;
import com.ffcs.crmd.tsp.core.thread.ThreadFactoryImpl;
import com.ffcs.crmd.tsp.task.config.TaskConfig;
import com.ffcs.crmd.tsp.task.container.ThreadPoolContainer;
import com.ffcs.crmd.tsp.task.log.TaskLogger;
import com.ffcs.crmd.tsp.task.netty.NettyConfig;
import com.ffcs.crmd.tsp.task.threadpool.JobProcessBusinessThreadPool;
import com.ffcs.crmd.tsp.task.threadpool.JobProcessThreadPool;

/**
 * 
 * 功能说明:客户端实例
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class TspTaskIntance {
    
    /**
     * 日志
     */
    private static final Logger          LOG                      = TaskLogger.getLogger(LoggerName.TaskLoggerName);
    
    /**
     * 任务通信端Id(标识)
     */
    private String                       clientId;
    
    /**
     * 任务通信端服务实现
     */
    private TspTaskImpl                  taskImpl;
    
    /**
     * 任务通信端配置
     */
    private NettyConfig                  nettyConfig;
    
    /**
     * 任务端配置
     */
    private TaskConfig                   taskConfig;
    
    /**
     * 轮询调度
     */
    private ScheduledExecutorService     scheduledExecutorService = Executors.newScheduledThreadPool(3,
        new ThreadFactoryImpl("TspTaskScheduledThread-", 10));
    
    /**
     * 任务处理线程池
     */
    private JobProcessThreadPool         jobProcessThreadPool;
    
    /**
     * 任务批量业务处理线程池
     */
    private JobProcessBusinessThreadPool jobProcessBusinessThreadPool;
    
    public TspTaskIntance(NettyConfig nettyConfig, TaskConfig taskConfig) {
        this.nettyConfig = nettyConfig;
        this.taskConfig = taskConfig;
        
        clientId = nettyConfig.buildClientId();
        
        jobProcessBusinessThreadPool = new JobProcessBusinessThreadPool(taskConfig.getJobProcessBusinessThread());
        jobProcessThreadPool = new JobProcessThreadPool(taskConfig.getJobProcessThread());
        
        ThreadPoolContainer.getInstance().register(jobProcessBusinessThreadPool);
        ThreadPoolContainer.getInstance().register(jobProcessThreadPool);
        taskImpl = new TspTaskImpl(nettyConfig);
    }
    
    /**
     * 
     * 功能说明:启动服务
     * 
     * @throws TspException
     * @throws TspException 
     */
    public void start() throws TspException {
        taskImpl.start();
        jobProcessThreadPool.start();
        jobProcessBusinessThreadPool.start();
        startScheduledTask();
        LOG.info("TSP-TASK: intance start ok - [{}].", clientId);
        System.out.println(String.format("TSP-TASK: intance start ok - [%s].", clientId));
    }
    
    /**
     * 
     * 功能说明:关闭服务
     * 
     * @throws TspException
     */
    public void shutdown() throws TspException {
        taskImpl.shutdown();
        jobProcessThreadPool.shutdown();
        jobProcessBusinessThreadPool.shutdown();
        scheduledExecutorService.shutdown();
        LOG.info("TSP-TASK: intance shutdown ok - [{}].", clientId);
        System.out.println(String.format("TSP-TASK: intance shutdown ok - [%s].", clientId));
    }
    
    /**
     * 
     * 功能说明:发送心跳到服务端
     *
     */
    private void sendHeartbeatToServer() {
        HeartbeatData heartbeatData = new HeartbeatData();
        TaskData taskData = new TaskData();
        taskData.setIp(nettyConfig.getClientIP());
        taskData.setIdentity(taskConfig.getIdentity());
        heartbeatData.setTaskData(taskData);
        heartbeatData.setClientID(clientId);
        for (String addr : nettyConfig.getServerAddrList()) {
            try {
                taskImpl.sendHeartBeat(addr, heartbeatData);
                LOG.info("TSP-TASK: instance[{}] send a heart beat to server[{}].", clientId, addr);
            } catch (TspRemotingException e) {
                LOG.error("TSP-TASK: instance[{}] send a heart beat to server exception:", clientId, addr, e);
            }
        }
    }
    
    /**
     * 
     * 功能说明:启动定时任务
     *
     */
    private void startScheduledTask() {
        // 定时发送心跳
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    TspTaskIntance.this.sendHeartbeatToServer();
                } catch (Throwable e) {
                    LOG.error("TSP-TASK: instance[{}] send heart beat to server[{}] exception:", TspTaskIntance.this.clientId,
                        TspTaskIntance.this.nettyConfig.getServerAddr(), e);
                }
            }
        }, 1000, nettyConfig.getHeartbeatBrokerInterval(), TimeUnit.MILLISECONDS);
        
        // 定时打印线程池情况
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    LOG.debug("------------------------------------------------------------------------------------------");
                    LOG.debug("|instance=[{}] print thread pool status info |", TspTaskIntance.this.clientId);
                    jobProcessBusinessThreadPool.printInfo();
                    jobProcessThreadPool.printInfo();
                } catch (Throwable e) {
                    LOG.error("TSP-TASK: instance[{}] print thread pool status info exception:", TspTaskIntance.this.clientId, e);
                }
            }
        }, 1000, taskConfig.getPrintThreadPoolInfoInterval(), TimeUnit.MILLISECONDS);
        
        scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    TspTaskIntance.this.taskImpl.retryReturnCompleteJobDetail();
                } catch (Throwable e) {
                    LOG.error("TSP-TASK: instance[{}] retry send return complete job detail exception:", TspTaskIntance.this.clientId, e);
                }
            }
        }, 1000, taskConfig.getRetryReturnCompleteJobDetailInterval(), TimeUnit.MILLISECONDS);
    }
    
}
